ASP.NET MVC 5在登入與權限控管中,微軟似乎是推薦使用ASP.NET Identity,最簡單的使用方式就是在新建專案時就將預設的無驗證改成第二項的個別使用者帳戶功能。
不過我在做小專案時,選的是無驗證,想體驗[AuthorizeAttribute]
的權限驗證功能,似乎最簡單的方式是使用.net早期的FormsAuthenticationu驗證,看別人的文章也講的很簡單,複製三段code,登入登出的功能就完成了。
小弟不幸的一用之下,我的登入功能在登入成功後又重新導回登入畫面,形成無窮迴圈卡了一個小時。
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel user)
{
if (ModelState.IsValid)
{
User u = _userService.Find(user.ID , user.Password);
if(u != null)
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
u.ID,
DateTime.UtcNow,
DateTime.UtcNow.AddMinutes(90),
isPersistent: true,
userData: u.Name,
cookiePath: FormsAuthentication.FormsCookiePath
);
string encTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
{
Secure = true,
HttpOnly = true
};
Response.Cookies.Add(cookie);
//return View();
return RedirectToAction("Index", "Lectures");
}
}
ModelState.AddModelError("", "無效的帳號或密碼。");
return View(user);
}
這個問題關鍵字很難下,一眼看過去會覺得大家的程式碼差不多,但問題發生的原因是在於我的程式碼比別人的Cookies有多了一個Secure = true
的設定,當下還真的覺得沒什麼,安全很重要,認為這是一個正常的設定,結果眉角在這裡。
Secure = true
的意思是要求瀏覽器這一個Cookie僅能在HTTPS連線下才能傳送給後端Server辨識身分,若無Https則不傳送。
所以我在使用Vistual Studio開發時,我的IIS Express是在Http環境下,登入成功後我使用的是RedirectToAction,會傳遞302狀態碼給瀏覽器,要求瀏覽器連線至我的另外一個Controller的Index Action,此時因為Cookie設定Secure的關係,瀏覽器發現不是https連線,所以就沒有把Cookie送到後端Server,後端沒拿到Cookie便認為我是未登入的使用者,就重新導向至登入畫面,呈現登入後一直卡在登入畫面的結果。
這樣的問題要解決就是強制網站使用Https來連線,在IIS與Azure App Service都有選項可以勾選來啟用https伺服器,在測試環境中用VS2017內建的IIS Express的SSL開啟方式請看我的另外一篇文章在Visual Studio 2017啟用IIS Express的Https
public ActionResult Logout()
{
FormsAuthentication.SignOut();
return RedirectToAction("Login");
}
在<system.web>
標籤中加入<authentication>
這一段標籤內容如下,其中loginUrl代表要導向的登入頁網址
<configuration>
...
<system.web>
...
<authentication mode="Forms">
<forms loginUrl="~/Users/Login" timeout="2880"></forms>
</authentication>
</system.web>
</configuration>
這是我的FB粉專,歡迎大家來按讚:FB:長庚的作業簿
還有我的部落格:Wordpress:長庚的作業簿